#ifndef ALFS_STDX_DEFAULT_DELETE_HPP
#define ALFS_STDX_DEFAULT_DELETE_HPP
#include    <alfs/config.hpp>

// File [alfs/stdx/default_delete.hpp].
//
// Note: this file is included by [alfs/stdx/memory.hpp], which also includes
// <memory>.  It can be used freestanding, or via [alfs/stdx/memory.hpp].
//
// (c) copyright Alf P. Steinbach 2008.
// Use, modification and distribution are subject to the "New BSD License"
// as listed at <url: http://www.opensource.org/licenses/bsd-license.php>.
//
// An implementation of std::default_delete for pre-C++0x compilers.

#include    <memory>

// ALFS_IS_CPP0X_OR_LATER           : 1 => default_delete provided by standard library.
// ALFS_DONT_DEFINE_DEFAULT_DELETE  : don't try to define it, please
// ALFS_DEFAULT_DELETE_EMULATION    : 1 =>  default_delete has been defined

#if !ALFS_IS_CPP0X_OR_LATER && !defined( ALFS_DONT_DEFINE_DEFAULT_DELETE ) && !(0+ALFS_DEFAULT_DELETE_EMULATION)
#   define ALFS_DEFAULT_DELETE_EMULATION    1
#   include <boost/checked_delete.hpp>      // Diagnostics for incomplete types.
#   include <boost/utility/enable_if.hpp>   // boost::enable_if
#   include "type_traits.hpp"               // std::is_convertible, std::has_virtual_destructor

    namespace std{

        template< class T >
        struct default_delete
        {
            default_delete() {}

            // The C++0x draft standard's intent for this constructor, is unclear.
            // The draft does not place any restrictions on this conversion (unsafe).
            // Also the draft spells the name incorrectly, so the spec is not 100%.
            template< class U >
            default_delete(
                default_delete<U> const&,
                typename boost::enable_if_c<
                    //std::is_convertible<T*, U*>::value && 
                    true //(alfs::HasVirtualDestructor<U>::value != alfs::no)
                    >::type* = 0
                )
            {}

            void operator()( T* p ) const
            {
                ::boost::checked_delete( p );
            }
        };

        template< class T >
        struct default_delete< T[] >
        {
            void operator()( T* p ) const
            {
                ::boost::checked_array_delete( p );
            }
        };

        template< class T, size_t N >
        struct default_delete< T[N] >
        {
            void operator()( T* p, size_t ) const
            {
                ::boost::checked_array_delete( p );
            }
        };
    }  // std
#else
#   define  ALFS_DEFAULT_DELETE_EMULATION 0
#endif


namespace alfs{
#if ALFS_IS_CPP0X_OR_LATER || ALFS_DEFAULT_DELETE_EMULATION
    template< typename T >
    inline void destroyPointee( T* p )
    {
        std::default_delete<T>()( p );
    }
#else
    template< typename T >
    inline void destroyPointee( T* p )
    {
        ::boost::checked_delete( p );
    }
#endif
}  // alfs


#endif
